package indi.storyoftime.rasite.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import indi.storyoftime.rasite.entity.Image;
import indi.storyoftime.rasite.mapper.ImageMapper;
import indi.storyoftime.rasite.util.GeoUtil;
import indi.storyoftime.rasite.util.ImageUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@Service
public class ImageService {

    @Autowired
    private ImageMapper imageMapper;

    /**
     * 根据id获取图片信息。
     */
    public Image getImageById(Integer id) {
        QueryWrapper<Image> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        wrapper.eq("is_deleted", 0);
        return imageMapper.selectOne(wrapper);
    }

    /**
     * 获取全部图片信息记录。
     * 限查询1000条记录。
     */
    public List<Image> getImages() {
        QueryWrapper<Image> wrapper = new QueryWrapper<>();
        wrapper.eq("is_deleted", 0);
        wrapper.orderBy(true, false, "id");
        wrapper.last("limit 1000");
        return imageMapper.selectList(wrapper);
    }

    /**
     * 分页获取图片信息。
     */
    public List<Image> getImagesByPage(Integer pageNo, Integer pageSize, String orderBy, Boolean desc) {
        QueryWrapper<Image> wrapper = new QueryWrapper<>();
        wrapper.eq("is_deleted", 0);
        wrapper.orderBy(true, !desc, orderBy);
        Page<Image> page = new Page<>(pageNo, pageSize);
        return imageMapper.selectPage(page, wrapper).getRecords();
    }

    public List<Image> getImagesByPage(Integer pageNo, Integer pageSize) {
        return getImagesByPage(pageNo, pageSize, "id", true);
    }

    /**
     * 使用limit获取图片信息。
     */
    public List<Image> getImagesByLimit(Integer offset, Integer limit, String orderBy, Boolean desc) {
        QueryWrapper<Image> wrapper = new QueryWrapper<>();
        wrapper.eq("is_deleted", 0);
        wrapper.orderBy(true, !desc, orderBy);
        wrapper.last("limit " + offset + "," + limit);

        return imageMapper.selectList(wrapper);
    }

    public List<Image> getImagesByLimit(Integer offset, Integer limit) {
        return getImagesByLimit(offset, limit, "id", true);
    }

    /**
     * 从上传的图片数据中提取图片信息。
     * @param file 上传的图片文件
     * @return Image对象，返回null代表提取失败
     */
    public Image parseImage(MultipartFile file) {
        Image image = new Image();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");

        // 处理上传的文件
        BufferedImage bufImage;
        Map<String, String> metadata;
        String md5;
        try {
            bufImage = ImageIO.read(file.getInputStream());
            metadata = ImageUtil.getMetaInfo(file.getInputStream());
            md5 = ImageUtil.getMD5(file.getInputStream());
        } catch (IOException e) {
            return null;
        }

        // 填入各字段信息
        image.setImageSize(file.getSize());
        image.setTags("[]");
        image.setMd5(md5);
        image.setLongitude(GeoUtil.degreeToDecimal(metadata.get("GPS Longitude")));
        image.setLatitude(GeoUtil.degreeToDecimal(metadata.get("GPS Latitude")));
        image.setAltitude(GeoUtil.parseValue(metadata.get("GPS Altitude")));
        Date shootingTime = null;
        try {
            shootingTime = sdf.parse(Objects.requireNonNull(metadata.get("Date/Time")));
        } catch (ParseException | NullPointerException ignored) {}
        image.setShootingTime(shootingTime);
        image.setResolution(String.format("%sx%s", bufImage.getWidth(), bufImage.getHeight()));
        image.setIsDeleted(0);

        return image;
    }

    /**
     * 使用上传的文件创建图片。
     * 返回成功插入的条数。
     */
    public Integer createImage(Image image) {
        return imageMapper.insert(image);
    }

    /**
     * 根据id更新图片信息。
     * 返回成功更新的条数。
     */
    public Integer updateImageById(Integer id, Image image) {
        image.setId(id);
        return imageMapper.updateById(image);
    }

    /**
     * 根据id删除图片信息记录。
     */
    public void deleteImageById(Integer id) {
        Image image = new Image();
        image.setIsDeleted(1);
        imageMapper.update(image, new QueryWrapper<Image>().eq("id", id));
    }
}
